home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 October / EnigmA AMIGA RUN 22 (1997)(G.R. Edizioni)(IT)[!][issue 1997-10 & 11][EAR-CD VI].iso / progs / devel / pcq12d_2 / examples / peep.p < prev    next >
Text File  |  1991-07-26  |  19KB  |  845 lines

  1. Program Optimizer;
  2.  
  3. {
  4.     Peep.p from PCQ Pascal
  5.  
  6. Peep is a peephole optimizer that works on the assembly code
  7. produced by PCQ Pascal.  It is not designed to work on any other
  8. code, so be careful.  It reads in the assembly program, optimizes
  9. whatever it can, then writes out a slightly shorter, slightly
  10. faster equivalent file.
  11.  
  12. Peep makes all sorts of assumptions about the source code, one of
  13. which is that the source code is correct.  For example, if an
  14. instruction takes two operands, Peep expects there to be two
  15. operands.  That's O.K. for the compiler output, but you might run
  16. into trouble if you tried using it on normal assembly programs.
  17. It is highly unlikely that anything written in assembly could be
  18. improved by Peep anyway.
  19.  
  20. Using Peep is entirely optional.
  21. }
  22.  
  23.  
  24.  
  25. {$I "Include:Utils/StringLib.i"}
  26. {$I "Include:Utils/Parameters.i"}
  27. {$I "Include:Utils/Break.i"}
  28.  
  29. Const
  30.     MaxPeeps = 199;
  31.  
  32. type
  33.     Operation = (
  34.         op_ADD,
  35.         op_ADDA,
  36.         op_ADDQ,
  37.         op_AND,
  38.         op_ASL,
  39.         op_ASR,
  40.         op_BCC,
  41.         op_BCS,
  42.         op_BEQ,
  43.         op_BGE,
  44.         op_BGT,
  45.         op_BHI,
  46.         op_BLE,
  47.         op_BLS,
  48.         op_BLT,
  49.         op_BNE,
  50.         op_BPL,
  51.         op_BRA,
  52.         op_BSET,
  53.         op_CLR,
  54.         op_CMP,
  55.         op_CNOP,
  56.         op_DBRA,
  57.         op_DC,
  58.         op_DIVS,
  59.         op_DIVU,
  60.         op_DS,
  61.         op_END,
  62.         op_EOR,
  63.         op_EXG,
  64.         op_EXT,
  65.         op_JMP,
  66.         op_JSR,
  67.         op_LEA,
  68.         op_LINK,
  69.         op_LSL,
  70.         op_LSR,
  71.         op_MOVE,
  72.         op_MOVEM,
  73.         op_MOVEQ,
  74.         op_MULS,
  75.         op_MULU,
  76.         op_NEG,
  77.         op_NOT,
  78.         op_OR,
  79.         op_PEA,
  80.         op_RTS,
  81.         op_SCC,
  82.         op_SCS,
  83.         op_SECTION,
  84.         op_SEQ,
  85.         op_SGE,
  86.         op_SGT,
  87.         op_SHI,
  88.         op_SLE,
  89.         op_SLS,
  90.         op_SLT,
  91.         op_SNE,
  92.         op_SUB,
  93.         op_SUBQ,
  94.         op_SWAP,
  95.         op_TRAP,
  96.         op_TST,
  97.         op_UNLK,
  98.         op_XDEF,
  99.         op_XREF,
  100.         op_None,
  101.         op_LABEL,
  102.         op_EOF);
  103.  
  104.     CodeCell = record
  105.     OpCode    : Operation;
  106.     OSize    : Char;
  107.     Deleted    : Boolean;
  108.     Operand1,
  109.     Operand2,
  110.     Trailer  : String;
  111.     Buffer    : Array [0..127] of Char;
  112.     end;
  113.     CodeCellPtr = ^CodeCell;
  114.  
  115.     PeepArray = Array [0..MaxPeeps] of CodeCell;
  116.  
  117. const
  118.  
  119. {
  120.     Count   : Array [0..12] of Integer = (0,0,0,0,0,0,0,0,0,0,0,0,0);
  121.  
  122.     Desc    : Array [0..12] of String = (
  123.         "move 0 to clear          ",
  124.         "remove middleman in move ",
  125.         "swap MOVEQ for AND $FFFF ",
  126.         "reuse data register      ",
  127.         "don't reload Dn          ",
  128.         "remove 0 test for dest=Dn",
  129.         "remove 0 test for src=Dn ",
  130.         "strip rts trailers       ",
  131.         "remove tst               ",
  132.         "tst, don't move          ",
  133.         "don't and with #255      ",
  134.         "lose test in Scc/Bcc     ",
  135.         "swap beq/bra             ");
  136. }
  137.     OpCodes : Array [op_ADD..op_XREF] of String = (
  138.         "add",
  139.         "adda",
  140.         "addq",
  141.         "and",
  142.         "asl",
  143.         "asr",
  144.         "bcc",
  145.         "bcs",
  146.         "beq",
  147.         "bge",
  148.         "bgt",
  149.         "bhi",
  150.         "ble",
  151.         "bls",
  152.         "blt",
  153.         "bne",
  154.         "bpl",
  155.         "bra",
  156.         "bset",
  157.         "clr",
  158.         "cmp",
  159.         "cnop",
  160.         "dbra",
  161.         "dc",
  162.         "divs",
  163.         "divu",
  164.         "ds",
  165.         "end",
  166.         "eor",
  167.         "exg",
  168.         "ext",
  169.         "jmp",
  170.         "jsr",
  171.         "lea",
  172.         "link",
  173.         "lsl",
  174.         "lsr",
  175.         "move",
  176.         "movem",
  177.         "moveq",
  178.         "muls",
  179.         "mulu",
  180.         "neg",
  181.         "not",
  182.         "or",
  183.         "pea",
  184.         "rts",
  185.         "scc",
  186.         "scs",
  187.         "section",
  188.         "seq",
  189.         "sge",
  190.         "sgt",
  191.         "shi",
  192.         "sle",
  193.         "sls",
  194.         "slt",
  195.         "sne",
  196.         "sub",
  197.         "subq",
  198.         "swap",
  199.         "trap",
  200.         "tst",
  201.         "unlk",
  202.         "xdef",
  203.         "xref");
  204.  
  205. var
  206.     FirstPeep,
  207.     LastPeep    : Integer;
  208.     PeepHole    : PeepArray;
  209.     InputLine    : String;
  210.     InputFileName : String;
  211.     InputFile    : Text;
  212.     OutputFileName : String;
  213.     OutputFile    : Text;
  214.     EndOfFile    : Boolean;
  215.     Changed    : Boolean;
  216.  
  217.  
  218.  
  219. Procedure Die(ExitCode : Integer);
  220. begin
  221.     Close(InputFile);
  222.     Close(OutputFile);
  223.     Exit(ExitCode);
  224. end;
  225.  
  226. Procedure FindOperand(var c : CodeCell; SymText : String);
  227.  
  228. {
  229.     This just does a binary chop search of the list of operations
  230. }
  231.  
  232. var
  233.     top,
  234.     middle,
  235.     bottom    : Operation;
  236.     compare    : Short;
  237. begin
  238.     Bottom := op_ADD;
  239.     Top := op_XREF;
  240.  
  241.     compare := strpos(SymText, '.');
  242.     if compare = -1 then
  243.     c.OSize := ' '
  244.     else begin
  245.     c.OSize := SymText[Succ(Compare)];
  246.     SymText[compare] := '\0';
  247.     end;
  248.  
  249.     while Bottom <= Top do begin
  250.     middle := Operation((Byte(bottom) + Byte(top)) shr 1);
  251.     Compare := stricmp(OpCodes[Middle], SymText);
  252.     if Compare = 0 then begin
  253.         c.Opcode := Middle;
  254.         return;
  255.     end else if Compare < 0 then
  256.         Bottom := Succ(Middle)
  257.     else
  258.         Top := Pred(Middle);
  259.     end;
  260.     Writeln('Unknown instruction "', SymText, '"');
  261.     Die(10);
  262. end;
  263.  
  264. Procedure ReadWord(InLine : String; var pos : Integer;
  265.             var dest : String; delim : Char);
  266. begin
  267.     while isspace(InLine[pos]) do
  268.     Inc(pos);
  269.     dest := Adr(Inline[pos]);
  270.     while (not isspace(Inline[pos])) and
  271.       (Inline[pos] <> '\0') and
  272.       (Inline[pos] <> delim) do
  273.     Inc(pos);
  274.     Inline[pos] := '\0';
  275.     Inc(pos);
  276. end;
  277.  
  278. Procedure ReadInstruction(var c : CodeCell);
  279. var
  280.     OpStorage : String;
  281.     Leave     : Boolean;
  282.     InputPos,
  283.     LastPos   : Integer;
  284. begin
  285.     with c do begin
  286.     OpCode := op_NONE;
  287.     OSize  := ' ';
  288.     Deleted:= False;
  289.     Operand1 := "";
  290.     Operand2 := "";
  291.     Trailer  := "";
  292.     InputLine := Adr(c.Buffer);
  293.     end;
  294.     repeat
  295.     Leave := True;
  296.     repeat
  297.         if eof(InputFile) then begin
  298.         c.OpCode := op_EOF;
  299.         return;
  300.         end;
  301.         ReadLn(InputFile, InputLine);
  302.     until (strlen(InputLine) > 0) and (InputLine[0] <> '*');
  303.  
  304.     if isspace(InputLine[0]) then begin { It's not a label }
  305.         InputPos := 0;
  306.         ReadWord(InputLine, InputPos, OpStorage, '\0');
  307.         if strlen(OpStorage) > 0 then begin
  308.         FindOperand(c, OpStorage);
  309.         case c.OpCode of
  310.           op_ADD..op_ASR,
  311.           op_BSET,op_CMP..op_DBRA,
  312.           op_DIVS,op_DIVU,op_EOR,op_EXG,
  313.           op_LEA..op_MULU,
  314.           op_OR, op_SECTION,op_SUB, OP_SUBQ :
  315.             begin
  316.                 ReadWord(InputLine, InputPos, c.Operand1, ',');
  317.                 ReadWord(InputLine, InputPos, c.Operand2, '\0');
  318.             end;
  319.           op_BCC..op_BRA,op_CLR,
  320.           op_EXT,op_JMP,op_JSR,
  321.           op_NEG,op_NOT,op_PEA,
  322.           op_SCC..op_SNE,
  323.           op_SWAP..op_UNLK,
  324.           op_XDEF,op_XREF :
  325.             begin
  326.                 ReadWord(InputLine, InputPos, c.Operand1, '\0');
  327.             end;
  328.           op_DC, OP_DS :
  329.             begin
  330.                 while isspace(InputLine[InputPos]) do
  331.                 Inc(InputPos);
  332.                 c.Operand1 := Adr(InputLine[Inputpos]);
  333.             end;
  334.           op_END,op_RTS : ;
  335.         end;
  336.         end else
  337.         Leave := False;
  338.     end else     { It's a label }
  339.         c.OpCode := op_LABEL;
  340.  
  341.     until Leave;
  342. end;
  343.  
  344.  
  345. Procedure FillPeepholeArray;
  346. var
  347.     WasLabel : Boolean;
  348. begin
  349.     LastPeep := 0;
  350.     FirstPeep := 0;
  351.     repeat
  352.     ReadInstruction(PeepHole[LastPeep]);
  353.     WasLabel := PeepHole[LastPeep].OpCode = op_LABEL;
  354.     Inc(LastPeep);
  355.     until WasLabel or (LastPeep > MaxPeeps) or (EOF(InputFile));
  356. end;
  357.  
  358.  
  359. Procedure WriteInstruction(CellNum : Integer);
  360. begin
  361.     with PeepHole[CellNum] do begin
  362.  
  363.     if OpCode = op_EOF then
  364.         return;
  365.  
  366.     if Deleted then
  367.         return;
  368.  
  369.     if OpCode = op_LABEL then begin
  370.         Writeln(OutputFile, String(Adr(Buffer)));
  371.         return;
  372.     end;
  373.  
  374.     Write(OutputFile, '\t', OpCodes[OpCode]);
  375.  
  376.     if OSize <> ' ' then
  377.         write(OutputFile, '.', OSize);
  378.  
  379.     if strlen(Operand1) > 0 then
  380.         Write(OutputFile, '\t', Operand1);
  381.  
  382.     if strlen(Operand2) > 0 then
  383.         Write(OutputFile, ',', Operand2);
  384.  
  385.     Writeln(OutputFile);
  386.     end;
  387. end;
  388.  
  389. Procedure EmptyPeepholeArray;
  390. var
  391.     i : Integer;
  392. begin
  393.     for i := FirstPeep to Pred(LastPeep) do
  394.     WriteInstruction(i);
  395. end;
  396.  
  397. Function NextInstruction(Current : Integer) : Integer;
  398. begin
  399.     repeat
  400.     Inc(Current);
  401.     if Current > LastPeep then
  402.         NextInstruction := -1;
  403.     until not PeepHole[Current].Deleted;
  404.     NextInstruction := Current;
  405. end;
  406.  
  407. Function IsDataRegister(op : String) : Boolean;
  408. begin
  409.     IsDataRegister := (strlen(op) = 2) and
  410.               (toupper(op[0]) = 'D') and
  411.               isdigit(op[1]);
  412. end;
  413.  
  414.  
  415. Function IsAddressRegister(op : String) : Boolean;
  416. begin
  417.     IsAddressRegister := ((strlen(op) = 2) and
  418.              (toupper(op[0]) = 'A') and
  419.              isdigit(op[1])) or
  420.              strieq(op, "sp");
  421. end;
  422.  
  423.  
  424. Function IsRegister(op : String) : Boolean;
  425. begin
  426.     IsRegister := (strlen(op) = 2) and
  427.           ((toupper(op[0]) = 'A') or (toupper(op[0]) = 'D')) and
  428.           isdigit(op[1]);
  429. end;
  430.  
  431. {
  432.     Carry out optimizations in a three-instruction window.
  433.     The optimizations are:
  434.  
  435.     scc    Dn
  436.     tst.b    Dn    =>  scc    Dn
  437.     beq    lab        b~cc   lab
  438.  
  439.     scc    Dn
  440.     tst.b    Dn    =>  scc    Dn
  441.     bne    lab     =>  bcc    lab
  442.  
  443.     move.x    ??,Dn
  444.     any.x    ???,Dn    =>  any.x  ???,??  not done - sub and add
  445.     move.x    Dn,??               require one operand to
  446.                        be a register
  447.  
  448.     beq    lab1
  449.     bra    lab2    =>  bne   lab2  (happens in case statements)
  450.     lab1            lab1
  451. }
  452.  
  453. Procedure Optimize3(Op1 : Integer);
  454. var
  455.     Op2, Op3 : Integer;
  456. begin
  457.     if Peephole[Op1].Deleted then
  458.     return;
  459.  
  460.     Op2 := NextInstruction(Op1);
  461.     if Op2 = -1 then
  462.     return;
  463.     Op3 := NextInstruction(Op2);
  464.     if Op3 = -1 then
  465.     return;
  466.  
  467. {    if (Peephole[Op1].OpCode = op_MOVE) and
  468.     (Peephole[Op3].OpCode = op_MOVE) and
  469.     (Peephole[Op1].OSize = Peephole[Op3].OSize) and
  470.     IsDataRegister(Peephole[Op1].Operand2) and
  471.     streq(Peephole[Op1].Operand1,Peephole[Op3].Operand2) and
  472.     streq(Peephole[Op1].Operand2,Peephole[Op3].Operand1) then begin
  473.     case Peephole[Op2].OpCode of
  474.       op_ADD..op_ASR,
  475.       op_CMP,op_DIVS,op_DIVU,
  476.       op_EOR,
  477.       op_LSL,op_LSR,
  478.       op_MULS,op_MULU,op_OR,
  479.       op_SUB,op_SUBQ :
  480.         if (Peephole[Op2].OSize = Peephole[Op1].OSize) and
  481.             streq(Peephole[Op2].Operand2,Peephole[Op1].Operand2) then begin
  482.             Peephole[Op2].Operand2 := Peephole[Op1].Operand1;
  483.             Peephole[Op1].Deleted := True;
  484.             Peephole[Op3].Deleted := True;
  485.             Changed := True;
  486.         end;
  487.       op_CLR,op_NEG,
  488.       op_NOT,op_TST :
  489.         if (Peephole[Op2].OSize = Peephole[Op1].OSize) and
  490.             streq(Peephole[Op2].Operand1,Peephole[Op1].Operand2) then begin
  491.             Peephole[Op2].Operand1 := Peephole[Op1].Operand1;
  492.             Peephole[Op1].Deleted := True;
  493.             Peephole[Op3].Deleted := True;
  494.             Changed := True;
  495.         end;
  496.     end;
  497.     end else} if ((Peephole[Op1].OpCode >= op_SCC) or
  498.         (Peephole[Op1].OpCode <= op_SNE)) and
  499.         IsDataRegister(Peephole[Op1].Operand1) and
  500.         (Peephole[Op2].OpCode = op_TST) and
  501.         streq(Peephole[Op1].Operand1, Peephole[Op2].Operand1) and
  502.         ((Peephole[Op3].OpCode = op_BEQ) or
  503.         (Peephole[Op3].OpCode = op_BNE)) then begin
  504.     if Peephole[Op3].OpCode = op_BEQ then begin
  505.         case Peephole[Op1].OpCode of
  506.           op_SEQ : Peephole[Op3].OpCode := op_BNE;
  507.           op_SGE : Peephole[Op3].OpCode := op_BLT;
  508.           op_SGT : Peephole[Op3].OpCode := op_BLE;
  509.           op_SLE : Peephole[Op3].OpCode := op_BGT;
  510.           op_SLT : Peephole[Op3].OpCode := op_BGE;
  511.           op_SNE : Peephole[Op3].OpCode := op_BEQ;
  512.           op_SLS : Peephole[Op3].OpCode := op_BHI;
  513.           op_SCS : Peephole[Op3].OpCode := op_BCC;
  514.           op_SCC : Peephole[Op3].OpCode := op_BCS;
  515.           op_SHI : Peephole[Op3].OpCode := op_BLS;
  516.         end;
  517.     end else begin
  518.         case Peephole[Op1].OpCode of
  519.           op_SEQ : Peephole[Op3].OpCode := op_BEQ;
  520.           op_SGE : Peephole[Op3].OpCode := op_BGE;
  521.           op_SGT : Peephole[Op3].OpCode := op_BGT;
  522.           op_SLE : Peephole[Op3].OpCode := op_BLE;
  523.           op_SLT : Peephole[Op3].OpCode := op_BLT;
  524.           op_SNE : Peephole[Op3].OpCode := op_BNE;
  525.           op_SCC : Peephole[Op3].OpCode := op_BCC;
  526.           op_SHI : Peephole[Op3].OpCode := op_BHI;
  527.           op_SLS : Peephole[Op3].OpCode := op_BLS;
  528.           op_SCS : Peephole[Op3].OpCode := op_BCS;
  529.         end;
  530.     end;
  531.     Peephole[Op2].Deleted := True;
  532.     Changed := True;
  533.     { Inc(Count[11]); }
  534.     end else if (Peephole[Op1].OpCode = op_BEQ) and
  535.         (Peephole[Op2].OpCode = op_BRA) and
  536.         (Peephole[Op3].OpCode = op_LABEL) and
  537.         streq(Peephole[Op1].Operand1,Adr(Peephole[Op3].Buffer)) then begin
  538.     Peephole[Op2].OpCode := op_BNE;
  539.     Peephole[Op1].Deleted := True;
  540.     Changed := True;
  541.     { Inc(Count[12]); }
  542.     end;
  543. end;
  544.  
  545. {
  546.     Carry out optimizations in a two-instruction window.
  547.     The optimizations are:
  548.  
  549.     move.x    ??,Dn
  550.     move.x    Dn,???    =>    move.x    ??,??? (?? <> (a0)+ )
  551.  
  552.     move.x    ??,Dn
  553.     add.x    Dn,???    =>    add.l    ??,???
  554.  
  555.     move.x    Dn,???
  556.     move.x    ???,Dn    =>    move.x    Dn,???
  557.  
  558.     move.x    Dn,???        move.x    Dn,???
  559.     move.x    ???,??    =>    move.x    Dn,??
  560.  
  561.     any.x    ??,Dn
  562.     cmp.x    #0,Dn    =>    any.x    ??,Dn
  563.  
  564.     move.x    Dn,??
  565.     cmp.x    #0,Dn    =>    move.x    Dn,?? (?? <> An)
  566.  
  567.     rts
  568.     anything    =>    rts
  569.  
  570.     any.x    ??,Dn
  571.     tst.x    Dn    =>    any.x    ??,Dn
  572.  
  573.     any.x    Dn
  574.     tst.x    Dn    =>    any.x    Dn
  575.  
  576.     move.x    ??,Dn    =>    tst.x    ??
  577.     scc    Dn        scc    Dn
  578.  
  579.     move.b    #?,Dn
  580.     and.x    #255,Dn    =>    move.x    #?,Dn
  581.  
  582.     move.w    ??,Dn        moveq    #0,Dn
  583.     and.l    #65535,Dn =>    move.w    ??,Dn
  584.  
  585. }
  586.  
  587. Procedure Optimize2(Op1 : Integer);
  588. var
  589.     Op2 : Integer;
  590. begin
  591.     if Peephole[Op1].deleted then
  592.     return;
  593.  
  594.     Op2 := NextInstruction(Op1);
  595.     if Op2 = -1 then
  596.     return;
  597.  
  598.     if (Peephole[Op1].OpCode = op_MOVE) and
  599.     (Peephole[Op2].OpCode = op_MOVE) and
  600.     (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  601.  
  602.     if IsDataRegister(Peephole[Op1].Operand1) and
  603.        streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) then begin
  604.  
  605.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) then begin
  606.         Peephole[Op2].Deleted := True;
  607.         { Inc(Count[4]); }
  608.         end else begin
  609.         Peephole[Op2].Operand1 := Peephole[Op1].Operand1;
  610.         { Inc(Count[3]); }
  611.         end;
  612.         Changed := True;
  613.     end else if IsRegister(Peephole[Op1].Operand2) and
  614.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) and
  615.         (not streq(Peephole[Op1].Operand1,"(a0)+")) and
  616.         (not IsRegister(Peephole[Op2].Operand2)) then begin
  617.         Peephole[Op1].Operand2 := Peephole[Op2].Operand2;
  618.         Peephole[Op2].Deleted := True;
  619.         Changed := True;
  620.         { Inc(Count[1]); }
  621.     end;
  622.     end else if Peephole[Op1].OpCode = op_RTS then begin
  623.     case Peephole[Op2].OpCode of
  624.       op_ADD..op_CMP,
  625.       op_DBRA,op_DIVU,
  626.       op_EOR..op_RTS,
  627.       op_SCC..op_SCS,
  628.       op_SEQ..op_UNLK : begin
  629.                 Peephole[Op2].Deleted := True;
  630.                 Changed := True;
  631.                 { Inc(Count[7]); }
  632.                 end;
  633.     end;
  634.     end else if (Peephole[Op2].OpCode = op_CMP) and
  635.         (streq(Peephole[Op2].Operand1,"#0") or
  636.          streq(Peephole[Op2].Operand1, "#$0")) and
  637.         IsDataRegister(Peephole[Op2].Operand2) then begin
  638.     case Peephole[Op1].OpCode of
  639.       op_NEG,op_NOT,op_EXT :
  640.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) and
  641.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  642.             Peephole[Op2].Deleted := True;
  643.             Changed := True;
  644.             { Inc(Count[5]); }
  645.         end;
  646.       op_ADD,op_ADDQ,op_AND,
  647.       op_ASL,op_ASR,op_DIVS,op_DIVU,op_EOR,
  648.       op_EXG,op_LSL,op_LSR,
  649.       op_MULS,op_MULU,op_OR,
  650.       op_SUB,op_SUBQ :
  651.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  652.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  653.             Peephole[Op2].Deleted := True;
  654.             Changed := True;
  655.             { Inc(Count[5]); }
  656.         end;
  657.       op_MOVE, op_MOVEQ :
  658.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  659.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  660.             Peephole[Op2].Deleted := True;
  661.             Changed := True;
  662.             { Inc(Count[5]); }
  663.         end else if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) and
  664.             (Peephole[Op1].OSize = Peephole[Op2].OSize) and
  665.             (not IsAddressRegister(Peephole[Op1].Operand1)) then begin
  666.             Peephole[Op2].Deleted := True;
  667.             Changed := True;
  668.             { Inc(Count[6]); }
  669.         end;
  670.     end;
  671.     end else if (Peephole[Op2].OpCode = op_TST) and
  672.         IsDataRegister(Peephole[Op2].Operand1) then begin
  673.     case Peephole[Op1].OpCode of
  674.       op_NEG,op_NOT,op_EXT :
  675.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand1) and
  676.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  677.             Peephole[Op2].Deleted := True;
  678.             Changed := True;
  679.             { Inc(Count[8]); }
  680.         end;
  681.       op_ADD,op_ADDQ,op_AND,
  682.       op_ASL,op_ASR,op_DIVS,op_DIVU,op_EOR,
  683.       op_EXG,op_LSL,op_LSR,
  684.       op_MOVE,op_MOVEQ,op_MULS,op_MULU,
  685.       op_OR,op_SUB,op_SUBQ :
  686.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) and
  687.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  688.             Peephole[Op2].Deleted := True;
  689.             Changed := True;
  690.             { Inc(Count[8]); }
  691.         end;
  692.     end;
  693.     end else if (Peephole[Op1].OpCode = op_MOVE) and
  694.         (Peephole[Op2].OpCode >= op_SCC) and
  695.         (Peephole[Op2].OpCode <= op_SNE) and
  696.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) then begin
  697.     with Peephole[Op1] do begin
  698.         OpCode := op_TST;
  699.         Operand2 := "";
  700.     end;
  701.     { Inc(Count[9]); }
  702.     Changed := True;
  703.     end else if (Peephole[Op1].OpCode = op_MOVE) and
  704.         (Peephole[Op1].Operand1[0] = '#') and
  705.         (Peephole[Op2].OpCode = op_AND) and
  706.         streq(Peephole[Op2].Operand1,"#255") and
  707.         IsDataRegister(Peephole[Op1].Operand2) and
  708.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  709.         (Peephole[Op1].OSize = 'b') then begin
  710.     Peephole[Op1].OSize := Peephole[Op2].OSize;
  711.     Peephole[Op2].Deleted := True;
  712.     Changed := True;
  713.     { Inc(Count[10]); }
  714.      end else if (Peephole[Op1].OpCode = op_MOVE) and
  715.          (Peephole[Op2].OpCode = op_AND) and
  716.          IsDataRegister(Peephole[Op1].Operand2) and
  717.          streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  718.          streq(Peephole[Op2].Operand1,"#65535") and
  719.          (Peephole[Op1].OSize = 'w') and
  720.          (Peephole[Op2].OSize = 'l') then begin
  721.  
  722.     Peephole[Op2].OpCode := op_MOVE;
  723.     Peephole[Op2].Operand1 := Peephole[Op1].Operand1;
  724.     Peephole[Op2].OSize := 'w';
  725.  
  726.     Peephole[Op1].OpCode := op_MOVEQ;
  727.     Peephole[Op1].OSize := ' ';
  728.     Peephole[Op1].Operand1 := "#0";
  729.  
  730.     Changed := True;
  731.     { Inc(Count[2]); }
  732. {    end else if (Peephole[Op1].OpCode = op_MOVE) and
  733.         (Peephole[Op2].OpCode = op_CMP) and
  734.         IsDataRegister(Peephole[Op1].Operand2) and
  735.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  736.         (Peephole[Op2].Operand1[0] = '#') and
  737.         (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  738.     Peephole[Op2].Operand2 := Peephole[Op1].Operand1;
  739.     Peephole[Op1].Deleted := True;
  740.     Changed := True; }
  741.     end;
  742. end;
  743.  
  744. {
  745.     Carry out optimizations in a one-instruction window.
  746.     The optimizations are:
  747.  
  748.     move.x    #0,??    =>    clr.x ?? (if x <> l and ?? <> Dn )
  749. }
  750.  
  751. Procedure Optimize1(Op : Integer);
  752. begin
  753.     if Peephole[Op].Deleted then
  754.     return;
  755.  
  756.     with Peephole[Op] do begin
  757.     if (OpCode = op_MOVE) and
  758.        (streq(Operand1, "#0") or streq(Operand1, "#$0")) and
  759.        ((not IsDataRegister(Operand2)) or (OSize <> 'l')) then begin
  760.         Operand1 := Operand2;
  761.         Operand2 := "";
  762.         OpCode := op_CLR;
  763.         Changed := True;
  764.         { Inc(Count[0]); }
  765.     end;
  766.     end;
  767. end;
  768.  
  769. {
  770. Procedure ReadCounts;
  771. var
  772.     CountFile : Text;
  773.     i    : Integer;
  774. begin
  775.     if reopen("Work:Pascal/1.2/peep_counts.txt", CountFile) then begin
  776.     for i := 0 to 12 do
  777.         readln(CountFile, Count[i]);
  778.     Close(CountFile);
  779.     end;
  780. end;
  781.  
  782. Procedure WriteCounts;
  783. var
  784.     CountFile : Text;
  785.     i : Integer;
  786. begin
  787.     if open("work:pascal/1.2/peep_counts.txt", CountFile) then begin
  788.     for i := 0 to 12 do begin
  789.         writeln(CountFile, Count[i]);
  790.         writeln(Desc[i], ' : ', Count[i]);
  791.     end;
  792.     Close(CountFile);
  793.     end;
  794. end;
  795. }
  796.  
  797. var
  798.     i : Integer;
  799. begin
  800.     Writeln('PCQ Peephole optimizer');
  801.  
  802.     InputFileName := AllocString(256);
  803.     OutputFileName := AllocString(256);
  804.  
  805.     GetParam(1,InputFileName);
  806.     GetParam(2,OutputFileName);
  807.  
  808.     if (strlen(InputfileName) <= 0) or 
  809.        (strlen(OutputFileName) <= 0) then begin
  810.     Writeln('Usage: Optimize filename');
  811.     Exit(20);
  812.     end;
  813.  
  814.   {  ReadCounts; }
  815.  
  816.     FirstPeep := 0;
  817.     LastPeep  := 0;
  818.  
  819.     if not open(OutputFileName, OutputFile) then begin
  820.     Writeln('Could not open output file: ', OutputFileName);
  821.     Exit(10);
  822.     end;
  823.  
  824.     if reopen(InputFileName, InputFile) then begin
  825.     while not eof(InputFile) do begin
  826.         FillPeepholeArray;
  827.         repeat
  828.         Changed := False;
  829.         for i := FirstPeep to LastPeep do begin
  830.             Optimize3(i);
  831.             Optimize2(i);
  832.             Optimize1(i);
  833.         end;
  834.         if CheckBreak then
  835.             Die(20);
  836.         until not Changed;
  837.         EmptyPeepholeArray;
  838.     end;
  839.  
  840.     { WriteCounts; }
  841.     Die(0);
  842.     end;
  843.  
  844. end.
  845.